#include "remote_functions.h"
#include <stdio.h>

// Remote function: add
cJSON *remote_add(const cJSON *params, RpcErrorCode *error_code)
{
  // 1. Validate parameters (MISRA emphasizes robustness and error checking).
  if (!cJSON_IsArray(params) || cJSON_GetArraySize(params) != 2)
  {
    *error_code = RPC_INVALID_PARAMS;
    return NULL;
  }
  cJSON *param1 = cJSON_GetArrayItem(params, 0);
  cJSON *param2 = cJSON_GetArrayItem(params, 1);
  if (!cJSON_IsNumber(param1) || !cJSON_IsNumber(param2))
  {
    *error_code = RPC_INVALID_PARAMS;
    return NULL;
  }

  // 2. Execute core logic.
  double result = param1->valuedouble + param2->valuedouble;

  // 3. Construct return value.
  *error_code = RPC_SUCCESS;
  return cJSON_CreateNumber(result);
}

// Remote function: get_user_info
cJSON *remote_get_user_info(const cJSON *params, RpcErrorCode *error_code)
{
  if (!cJSON_IsArray(params) || cJSON_GetArraySize(params) != 1)
  {
    *error_code = RPC_INVALID_PARAMS;
    return NULL;
  }
  cJSON *name_json = cJSON_GetArrayItem(params, 0);
  if (!cJSON_IsString(name_json))
  {
    *error_code = RPC_INVALID_PARAMS;
    return NULL;
  }

  printf("Server: Received request to get user info for '%s'\n", name_json->valuestring);

  UserProfile profile;
  // MISRA Rule 21.17: Use of strncpy is acceptable if the destination size is
  // checked and null-termination is guaranteed.
  strncpy(profile.name, name_json->valuestring, sizeof(profile.name) - 1);
  profile.name[sizeof(profile.name) - 1] = '\0'; // Ensure null-termination.
  profile.age = 30;
  strncpy(profile.city, "Mountain View", sizeof(profile.city) - 1);
  profile.city[sizeof(profile.city) - 1] = '\0';

  // Construct the JSON object to return.
  cJSON *result_obj = cJSON_CreateObject();
  if (result_obj == NULL)
  {
    *error_code = RPC_INTERNAL_ERROR;
    return NULL;
  }
  cJSON_AddStringToObject(result_obj, "name", profile.name);
  cJSON_AddNumberToObject(result_obj, "age", profile.age);
  cJSON_AddStringToObject(result_obj, "city", profile.city);

  *error_code = RPC_SUCCESS;
  return result_obj;
}

// Remote function: sum_and_print (demonstrates variadic params)
cJSON *remote_sum_and_print(const cJSON *params, RpcErrorCode *error_code)
{
  if (!cJSON_IsArray(params))
  {
    *error_code = RPC_INVALID_PARAMS;
    return NULL;
  }

  printf("Server: 'sum_and_print' called with %d arguments.\n", cJSON_GetArraySize(params));
  double sum = 0.0;
  cJSON *current_item = NULL;

  cJSON_ArrayForEach(current_item, params)
  {
    if (cJSON_IsNumber(current_item))
    {
      sum += current_item->valuedouble;
    }
    else if (cJSON_IsString(current_item))
    {
      printf("Server: Found a string in sum_and_print params: '%s'\n", current_item->valuestring);
    }
    // Other types are ignored.
  }

  *error_code = RPC_SUCCESS;
  return cJSON_CreateNumber(sum);
}

// --- THIS ENTIRE FUNCTION IS NEW ---
// Remote function: process_user_profile (demonstrates receiving a struct)
cJSON *remote_process_user_profile(const cJSON *params, RpcErrorCode *error_code)
{
  if (!cJSON_IsArray(params) || cJSON_GetArraySize(params) != 1)
  {
    *error_code = RPC_INVALID_PARAMS;
    return NULL;
  }
  cJSON *profile_json = cJSON_GetArrayItem(params, 0);
  if (!cJSON_IsObject(profile_json))
  {
    *error_code = RPC_INVALID_PARAMS;
    return NULL;
  }

  cJSON *name = cJSON_GetObjectItem(profile_json, "name");
  cJSON *age = cJSON_GetObjectItem(profile_json, "age");
  cJSON *city = cJSON_GetObjectItem(profile_json, "city");

  if (!cJSON_IsString(name) || !cJSON_IsNumber(age) || !cJSON_IsString(city))
  {
    *error_code = RPC_INVALID_PARAMS;
    return NULL;
  }

  printf("Server: Processed user profile -> Name: %s, Age: %.0f, City: %s\n",
         name->valuestring, age->valuedouble, city->valuestring);

  *error_code = RPC_SUCCESS;
  char confirmation_msg[128];
  snprintf(confirmation_msg, sizeof(confirmation_msg), "Successfully processed profile for %s.", name->valuestring);
  return cJSON_CreateString(confirmation_msg);
}
